package com.lifang.imgsoa.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.aliyun.openservices.ClientException;
import com.aliyun.openservices.oss.OSSClient;
import com.aliyun.openservices.oss.OSSException;
import com.aliyun.openservices.oss.model.CopyObjectResult;
import com.aliyun.openservices.oss.model.GetObjectRequest;
import com.aliyun.openservices.oss.model.ListObjectsRequest;
import com.aliyun.openservices.oss.model.OSSObjectSummary;
import com.aliyun.openservices.oss.model.ObjectListing;
import com.lifang.imgsoa.aop.BusinessException;

public abstract class OSSObjectUtilBase {
	
	private String bucketName = null;
	
	private OSSClient client = null;
	private OSSClient internalClient = null;
	
	protected OSSObjectUtilBase (String accessKeyID, String accessKeySecret, String bucketName) {
		this.bucketName = bucketName; 
		this.client = new OSSClient(accessKeyID, accessKeySecret);
		
		if (Global.ALIYUN_ECS == 1) {
			logger.info("internalClient 阿里云内网");
			this.internalClient = new OSSClient(Global.ALIYUN_INTERNAL, accessKeyID, accessKeySecret);
		} else {
			logger.info("internalClient 阿里云外网");
			this.internalClient = this.client;
		}
	}
	
	public static Logger logger = LoggerFactory.getLogger(OSSObjectUtilBase.class);
	
	
	public void uploadFile(Map<String, String> map) {
		try {
			int i = 1;
			int n = map.size();
			for (Map.Entry<String, String> entry : map.entrySet()) {
				
				logger.info("正在上传..bucketName={},..{}/{}..{}", bucketName, i++, n, entry.getKey());
				uploadFile(internalClient, bucketName, entry.getKey(), entry.getValue());
				logger.info("上传成功..");
			}

		} catch (Exception e) {
			logger.error("上传错误：", e);
			e.printStackTrace();
			throw new BusinessException(ErrorEnum.SOA_ERROR_100002);
		}
	}
	
	public void uploadFile_stream(Map<String, byte[]> map) {
		try {
			int i = 1;
			int n = map.size();
			for (Map.Entry<String, byte[]> entry : map.entrySet()) {
				
				logger.info("正在上传..bucketName={},..{}/{}..{}", bucketName, i++, n, entry.getKey());
				uploadFile_stream(internalClient, bucketName, entry.getKey(), entry.getValue());
				logger.info("上传成功..");
			}

		} catch (Exception e) {
			logger.error("上传错误：", e);
			e.printStackTrace();
			throw new BusinessException(ErrorEnum.SOA_ERROR_100002);
		}
	}
	
    
	public void uploadFile(String key, String fileName) {
		try {
			
			logger.info("正在上传..key={},...bucketName={},...{}", key, bucketName, fileName);
			uploadFile(internalClient, bucketName, key, fileName);
			logger.info("上传成功..");

		} catch (Exception e) {
			logger.error("上传错误：", e);
			e.printStackTrace();
			throw new BusinessException(ErrorEnum.SOA_ERROR_100002);
		}
	}
	
	public void uploadFile_stream(String key, byte[] filebytes) {
		try {
			
			logger.info("正在上传..key={},...bucketName={},...", key, bucketName);
			uploadFile_stream(internalClient, bucketName, key, filebytes);
			logger.info("上传成功..");

		} catch (Exception e) {
			logger.error("上传错误：", e);
			e.printStackTrace();
			throw new BusinessException(ErrorEnum.SOA_ERROR_100002);
		}
	}
    
    
	public File downloadFile(String key, String fileName) {
		File file = null;

		try {

			logger.info("正在下载..key={},...bucketName={},...{}", key, bucketName, fileName);
			file = downloadFile(internalClient, bucketName, key, fileName);
			logger.info("下载成功.." + fileName);

		} catch (Exception e) {
			logger.error("下载错误：", e);
			e.printStackTrace();
		}
		return file;

	}
    
    /**
     * 根据key删除文件
     */
    public void deleteFile(String key) {
        logger.info("正在删除..bucketName={},key={}", bucketName, key);
        internalClient.deleteObject(bucketName, key);
    	logger.info("删除成功..");
	}
    
    
    /**
     * 根据给定前坠 删除文件
     */
    public void deleteFile4prefix(String prefix) {
    	// 构造ListObjectsRequest请求
    	ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);

    	// 递归列出fun目录下的所有文件
    	listObjectsRequest.setPrefix(prefix);

    	ObjectListing listing = internalClient.listObjects(listObjectsRequest);

    	// 遍历所有Object
    	for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
    		deleteFile(objectSummary.getKey());
    	}
	}
    
    protected abstract void uploadFile(OSSClient client, String bucketName, String key, String filename) throws OSSException, ClientException, IOException;
    protected abstract void uploadFile_stream(OSSClient client, String bucketName, String key, byte[] filebytes) throws OSSException, ClientException, IOException;
    

    // 下载文件
    private File downloadFile(OSSClient client, String bucketName, String key, String filename) throws OSSException, ClientException {
    	File file = new File(filename);
        client.getObject(new GetObjectRequest(bucketName, key), file);
        return file;
    }
    
    //获得对象返回流
    public InputStream getObject(String key) throws IOException {

        // 获取Object的输入流
        return internalClient.getObject(bucketName, key).getObjectContent();
    }
    
    //拷贝Object
    public void copyObject(String srcKey, String destKey) {
        // 拷贝Object
        CopyObjectResult result = internalClient.copyObject(bucketName, srcKey, bucketName, destKey);

        // 打印结果
        // System.out.println("ETag: " + result.getETag() + " LastModified: " + result.getLastModified());
    }
    
    //剪切Object
    public void cutObject(String srcKey, String destKey) {
        // 拷贝Object
        logger.info("正在剪切..bucketName={},srcKey={},destKey={}", bucketName, srcKey, destKey);

        CopyObjectResult result = internalClient.copyObject(bucketName, srcKey, bucketName, destKey);
        internalClient.deleteObject(bucketName, srcKey);
       
        logger.info("剪切成功..");
    }
    
    
    /**
     * @param key
     * @param timeout
     * @param isInternal 是否 oss 内网调用
     * @return
     */
    //动态地生成一个经过签名的URL
    public String getUrl(String key, int timeout, boolean isInternal) {
        
        if (isInternal) {
            return internalClient.generatePresignedUrl(bucketName, key, new Date(new Date().getTime() + timeout)).toString();
        } else {
            return client.generatePresignedUrl(bucketName, key, new Date(new Date().getTime() + timeout)).toString();
        }
	}
    

	/**
	 * 得到暂时的http链接
	 * @param key
	 * @return
	 */
	public String getUrl(String key) {
		return getUrl(key, 60000, false);
	}
	public String getUrl4Internal(String key) {
	    return getUrl(key, 60000, true);
	}
	
}
